<?php

namespace app\backend\service;
use app\backend\controller\Member;
use app\common\model\MemberInviteModel;
use app\common\model\MemberLoginModel;
use app\common\model\MemberModel;
use app\common\model\MoneyCashModel;
use app\common\model\MoneyCensusModel;
use app\common\model\MoneyRecordModel;
use app\common\RootService;

class MemberService extends RootService
{
    /**
     * 置换标签
     * @return array
     */
    public function dataLabel()
    {
        return ['stateLabel' => MemberModel::$stateLabel, 'moneyLabel' => MoneyCensusModel::$moneyLabel,
            'typeLabel' => MemberModel::$typeLabel, 'bindType' => MemberModel::$bindType,
            'inviteType' => MemberInviteModel::$typeLabel, 'countryLabel' => MemberModel::$countryLabel];
    }

    /**
     * 用户列表
     * @param array $params
     * @return array
     * @throws \think\db\exception\DbException
     */
    public function lists(array $params)
    {
        // 数据源
        $memberList = $this->page($this->memberModel($params)->order(['m.id' => 'desc'])->with(['finance']));
        // 数据处理
        $memberList['data'] = $this->dataFormat($memberList['data']);
        // 处理结果
        return $memberList;
    }

    /**
     * 用户详情
     * @param int $memberId
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function detail(int $memberId)
    {
        // 筛选字段
        $memberInfo = $this->dataFormat($this->memberModel(['memberId' => $memberId])->select()->toArray())[0];
        $memberInfo['inviteCount'] = MemberInviteModel::where(['member_id' => $memberId, 'type' => 1])->count();
        return $memberInfo;
    }

    /**
     * 修改用户状态
     * @param array $params
     * @return array
     * @throws \app\common\RootException
     */
    public function switchState(array $params)
    {
        // 状态更新失败
        MemberModel::update(['id' => $params['memberId'], 'state' => $params['state'], 'remark' => $params['remark']]) || $this->errorException('用户状态修改失败');
        // 更新成功
        return ['msg' => '操作成功', 'reload' => true];
    }

    /**
     * 我的下线
     * @param array $params
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function fansList(array $params)
    {
        // 置换标签
        $dataLabel = $this->dataLabel();
        $type = ['mi.type', 'in', empty($params['type']) ? [1, 2, 3] : explode(',', $params['type'])];
        // 筛选条件
        $where = [['parent_id', '>', 0]];
        empty($params['type']) || $where[] = $type;
        // 邀请码筛选
        empty($params['invite']) || $params['memberId'] = MemberModel::where(['invite' => $params['invite']])->value('id');
        // 用户ID筛选
        empty($params['memberId']) || $where[] = ['m.parent_id', '=', $params['memberId']];
        // 注册日期筛选
        empty($params['createTime']) || $where[] = ['m.relation_time', 'between', betweenDate($params['createTime'])];
        // 筛选字段
        $fields = ['m.id', 'm.avatar', 'm.invite', 'm.type', 'm.email', 'm.parent_id', 'm.bind_type',
            'm.create_time', 'm.country', 'sum(if(mi.currency=0, amount, 0)) amount', // 贡献金币数量
            'm.state memberState', 'm.ip', 'm.device_id', 'm.device_sn', 'sum(if(mi.currency=3, amount, 0)) diamond', // 贡献钻石数量
            ];
        // 筛选模型
        $inviteFields = ['invite_id', 'amount', 'type', 'currency'];
        $inviteSql = MemberInviteModel::where(['type' => [1, 2, 3]])->field($inviteFields)->buildSql();
        $fansModel = MemberModel::alias('m')->join([$inviteSql => 'mi'], 'mi.invite_id = m.id', 'left');
        // 筛选结果
        $fansList = $this->page($fansModel->where($where)->field($fields)->group(['m.id'])->order(['m.id' => 'desc']));
        $parents = $this->parentList(array_column($fansList['data'], 'parent_id'));
        // 用户ID
        $memberIds = array_column($fansList['data'], 'id');
        // 资金数据
        $fundData = $this->fundData($memberIds);
        // 最后登录数据
        $loginData = $this->loginData($memberIds);
        // 数据处理
        array_walk($fansList['data'], function (&$row) use ($dataLabel, $fundData, $loginData, $parents) {
            $row['iconSum'] = $fundData[$row['id']]['iconSum'] ?? 0;// 消耗金币
            $row['diamondSum'] = $fundData[$row['id']]['diamondSum'] ?? 0;// 钻石合计
            $row['loginTime'] = $row['mbLogin']['create_time'] ?? '--';
            $row['bindType'] = $dataLabel['bindType'][$row['bind_type']] ?? '';
            $row['country'] = $dataLabel['countryLabel'][$row['country']] ?? $row['country'];
            $row['pInvite'] = $parents[$row['parent_id']]['invite'] ?? '';
            $row['mpStateLabel'] = $dataLabel['stateLabel'][$parents[$row['parent_id']]['pState'] ?? ''] ?? '';
            $row['loginIp'] = $loginData[$row['id']]['ip'] ?: '--';
            $row['loginDeviceSn'] = $loginData[$row['id']]['device_sn'] ?: '--';
            $row['loginTime'] = $loginData[$row['id']]['create_time'] ?: '--';
        });
        return $fansList;
    }

    /**
     * 邀请奖励
     * @param array $params
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function reward(array $params)
    {
        $dataLabel = $this->dataLabel();
        // 筛选结果
        $rewardList = $this->page($this->inviteRewardModel($params)->order(['actual' => 'desc']));
        // 用户ID
        $memberIds = array_column($rewardList['data'], 'parent_id');
        // 资金数据
        $fundData = $this->fundData($memberIds);
        // 最后登录数据
        $loginData = $this->loginData($memberIds);
        // 用户数据
        $parents = $this->parentList($memberIds);
        // 数据处理
        array_walk($rewardList['data'], function (&$row) use ($fundData, $dataLabel, $loginData, $parents) {
            $row['iconSum'] = $fundData[$row['parent_id']]['iconSum'] ?? 0;// 消耗金币
            $row['diamondSum'] = $fundData[$row['parent_id']]['diamondSum'] ?? 0;// 钻石合计
            $row['loginTime'] = $loginData[$row['parent_id']]['create_time'] ?: '--';
            isset($parents[$row['parent_id']]) && $row = array_merge($row, $parents[$row['parent_id']]);
            $row['bindType'] = $dataLabel['bindType'][$row['bind_type']] ?? '';
        });
        return $rewardList;
    }

    /**
     * 统计下线
     * @param array $memberIds
     * @param string $relationTime
     * @return mixed
     */
    protected function fans(array $memberIds)
    {
        // 筛选字段
        $fields = ['count(id) actual', 'count(case when bind_time is not null then id end) effect'];
        // 筛选结果
        return MemberModel::where(['parent_id' => $memberIds])->group('parent_id')->column($fields, 'parent_id');
    }

    /**
     * 邀请奖励
     * @param array $params
     * @return mixed
     */
    protected function inviteRewardModel(array $params)
    {
        // 筛选条件
        $where = [['m.parent_id', '>', 0]];
        $createTime = ['2022-05-01', date('Y-m-d H:i:s')];
        // 邀请码筛选
        empty($params['invite']) || $params['memberId'] = MemberModel::where(['invite' => $params['invite']])->value('id');
        // 用户ID筛选
        empty($params['memberId']) || $where[] = ['m.parent_id', '=', $params['memberId']];
        // 绑定上下级关系日期筛选
        if (!empty($params['createTime'])) {
            $createTime = betweenDate($params['createTime']);
            $where[] = ['m.relation_time', 'between', $createTime];
        }
        // 筛选字段
        $fields = [
            'm.parent_id',
            'count(m.id) actual', // 实际邀请
            "count(case when m.bind_time between '{$createTime[0]}' and '{$createTime[1]}' then m.id end) effect", // 有效邀请
            'mi.icon', // 下线贡献的金币数量
            'mi.diamond', // 下线贡献的钻石数量
        ];
        $invFields = ['member_id', 'sum(if(currency = 0, amount, 0)) icon', 'sum(if(currency = 3, amount, 0)) diamond'];
        $inviteSql = MemberInviteModel::where(['type' => [1, 2, 3]])->group(['member_id'])->field($invFields)->buildSql();
        // 筛选结果
        return MemberModel::alias('m')->join([$inviteSql => 'mi'], 'm.parent_id = mi.member_id', 'left')
            ->field($fields)->group('mi.member_id')->where($where);
    }

    /**
     * 获取父级用户信息
     * @param array $memberIds
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected function parentList(array $memberIds)
    {
        $fields = 'id, invite, email, avatar, ip, create_time, bind_type, state memberState, state pState';
        $memberList = MemberModel::where(['id' => $memberIds])->field($fields)->select()->toArray();
        return array_column($memberList, null, 'id');
    }

    /**
     * 统计用户资产
     * @param array $memberIds
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected function fundData(array $memberIds)
    {
        // 用户余额
        $fundData = arrColumn(MoneyCensusModel::where(['member_id' => $memberIds])->select()->toArray(), 'member_id');
        // 数据处理
        empty($fundData) || array_walk($fundData, function (&$rows) {
            $iconSum = $diamondSum = 0;
            // 拆分数据
            foreach ($rows as $row) {
                // 金币统计
                if (empty($row['currency'])) {
                    $iconSum += $row['amount'];
                    empty($row['type']) ? $icon = $row['amount'] : $iconConsume = $row['amount'];
                }
                // 钻石统计
                if (in_array($row['currency'], [3])) {
                    $diamondSum += $row['amount'];
                    empty($row['type']) ? $diamond = $row['amount'] : $diamondConsume = $row['amount'];
                }
            }
            $rows = ['icon' => $icon ?? 0, 'iconConsume' => $iconConsume ?? 0, 'iconSum' => $iconSum,
                'diamond' => $diamond ?? 0, 'diamondConsume' => $diamondConsume ?? 0, 'diamondSum' => $diamondSum];
        });
        return $fundData ?? [];
    }

    /**
     * 用户提现数据
     * @param array $memberIds
     * @return array|mixed
     */
    protected function cashData(array $memberIds)
    {
        // 分组条件
        $group = ['member_id', 'currency'];
        // 筛选条件
        $where = ['member_id' => $memberIds, 'state' => 3];
        // 筛选字段
        $fields = ['member_id', 'sum(receipt) receipt', 'currency'];
        // 筛选结果
        $cashData = arrColumn(MoneyCashModel::where($where)->field($fields)->group($group)->select()->toArray(), 'member_id');
        // 数据处理
        empty($cashData) || array_walk($cashData, function (&$rows){
            foreach ($rows as $row) {
                in_array($row['currency'], [2]) && $sb = $row['receipt']; // 币安
                in_array($row['currency'], [1]) && $curr = $row['receipt']; // 越南盾
                in_array($row['currency'], [4, 5]) && $curr = $row['receipt']; // 巴西雷亚尔
                in_array($row['currency'], [6, 7, 8, 9]) && $curr = $row['receipt']; // 印尼盾
            }
            $rows = ['curr' => $curr ?? 0, 'sb' => $sb ?? 0];
        });
        return $cashData;
    }

    /**
     * 最后登录数据
     * @param array $memberIds
     * @return array
     */
    protected function loginData(array $memberIds)
    {
        // 子查询
        $subSql = MemberLoginModel::where(['member_id' => $memberIds])->field(['max(id) id'])->group(['member_id'])->buildSql();
        // 登录数据
        $loginData = MemberLoginModel::alias('ml')->join([$subSql => 'mq'], 'ml.id = mq.id')
            ->field(['ml.*'])->select()->toArray();
        return array_column($loginData, null, 'member_id');
    }

    /**
     * 数据处理
     * @param array $dataList
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected function dataFormat(array $dataList)
    {
        // 置换标签
        $dataLabel = $this->dataLabel();
        // 用户ID
        $memberIds = array_column($dataList, 'id');
        // 下线统计
        $fans = $this->fans($memberIds);
        // 资金数据
        $fundData = $this->fundData($memberIds);
        // 提现数据
        $cashData = $this->cashData($memberIds);
        // 最后登录数据
        $loginData = $this->loginData(array_column($dataList, 'id'));
        // 数据处理
        array_walk($dataList, function (&$row) use ($dataLabel, $fundData, $cashData, $loginData, $fans) {
            $row['member_id'] = $row['id'];
            $row['cashSb'] = $cashData[$row['id']]['sb'] ?? 0; // 提现shib数量
            $row['effect'] = $fans[$row['id']]['effect'] ?? 0;// 实际邀请
            $row['actual'] = $fans[$row['id']]['actual'] ?? 0;// 有效邀请
            $row['cashVnd'] = realMoney($cashData[$row['id']]['curr'] ?? 0); // 提现发币
            $row['icon'] = $fundData[$row['id']]['icon'] ?? 0; // 金币余额
            $row['iconSum'] = $fundData[$row['id']]['iconSum'] ?? 0;// 消耗金币
            $row['iconConsume'] = $fundData[$row['id']]['iconConsume'] ?? 0;// 消耗金币
            $row['diamond'] = $fundData[$row['id']]['diamond'] ?? 0;// 钻石余额
            $row['diamondSum'] = $fundData[$row['id']]['diamondSum'] ?? 0;// 钻石合计
            $row['diamondConsume'] = $fundData[$row['id']]['diamondConsume'] ?? 0; // 消耗钻石
            $row['typeLabel'] = $dataLabel['typeLabel'][$row['mType']];
            $row['stateLabel'] = $dataLabel['stateLabel'][$row['state']];
            $row['bindType'] = $dataLabel['bindType'][$row['bind_type']] ?? '';
            $row['mpStateLabel'] = $dataLabel['stateLabel'][$row['mpState']] ?? '';
            $row['country'] = $dataLabel['countryLabel'][$row['country']] ?? $row['country'];
            $row['login'] = $loginData[$row['id']] ?? [];
            unset($row['finance']);
        });
        return $dataList;
    }

    /**
     * 用户模型
     * @param array $params
     * @param array $appendFields
     * @return mixed
     */
    protected function memberModel(array $params, array $appendFields = [])
    {
        // ip筛选
        empty($params['ip']) || $where[] = ['m.ip', '=', $params['ip']];
        // 用户ID筛选
        empty($params['memberId']) || $where[] = ['m.id', '=', $params['memberId']];
        // 设备ID筛选
        empty($params['deviceId']) || $where[] = ['m.device_id', '=', $params['deviceId']];
        // 邀请码筛选
        empty($params['invite']) || $where[] = ['m.invite', 'like', $params['invite'] . '%'];
        // 账号类型筛选
        condition($params['type'] ?? '') && $where[] = ['m.type', 'in', $params['type']];
        // 用户状态筛选
        condition($params['state'] ?? '') && $where[] = ['m.state', 'in', $params['state']];
        // 用户类型筛选
        condition($params['bindType'] ?? '') && $where[] = ['m.bind_type', 'in', $params['bindType']];
        // 注册时间筛选
        empty($params['createTime']) || $where[] = ['m.create_time', 'between', betweenDate($params['createTime'])];
        // 筛选字段
        $fields = ['m.id', 'm.avatar', 'm.account', 'm.nickname', 'm.device_sn', 'm.system', 'm.invite', 'm.create_time',
            'm.device_id', 'm.state', 'm.state memberState', 'm.ip', 'm.version', 'ifnull(mp.invite, "--") pInvite',
            'mp.state mpState', 'm.device_sn', 'm.type mType', 'm.remark', 'm.country', 'm.bind_type', 'm.parent_id', 'm.email'];
        // 子查询
        $parentMember = MemberModel::field(['id', 'invite', 'state'])->buildSql();
        // 筛选结果
        return MemberModel::alias('m')->join([$parentMember => 'mp'], 'm.parent_id = mp.id', 'left')
            ->where($where ?? [])->field(array_merge($fields, $appendFields))->group('m.id');
    }
}